package com.nosql.db.network;

import com.nosql.common.protocol.DBResponse;
import com.nosql.db.cluster.Node;
import com.nosql.db.core.storage.LSMStore;
import com.nosql.db.cluster.ClusterManager;
 import com.nosql.db.core.modul.Document;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class DBServer {
    private final int port;
    private final LSMStore storage;
    private final ClusterManager cluster;
    private ServerSocket serverSocket;
    private ExecutorService threadPool;

    public DBServer(int port, LSMStore storage, ClusterManager cluster) {
        this.port = port;
        this.storage = storage;
        this.cluster = cluster;
        this.threadPool = Executors.newCachedThreadPool();
    }

    public void start() throws IOException {
        serverSocket = new ServerSocket(port);
        System.out.println("Server started on port " + port);

        while (true) {
            Socket clientSocket = serverSocket.accept();
            threadPool.execute(new ClientHandler(clientSocket));
        }
    }

    private class ClientHandler implements Runnable {
        private final Socket socket;

        public ClientHandler(Socket socket) {
            this.socket = socket;
        }

        @Override
        public void run() {
            try (ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
                 ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream())) {
                
                // 添加连接建立日志
                System.out.println("[ClientHandler] 新客户端连接: " + socket.getRemoteSocketAddress());
                
                while (!socket.isClosed()) {
                    try {
                        Object obj = in.readObject();
                        
                        // 类型检查
                        if (!(obj instanceof DBCommand)) {
                            System.err.println("[ClientHandler] 收到非法命令类型: " + 
                                (obj != null ? obj.getClass().getName() : "null"));
                            
                            // 发送错误响应
                            out.writeObject(new DBResponse(
                                DBResponse.Status.ERROR, 
                                "非法请求类型: " + (obj != null ? obj.getClass().getName() : "null")));
                            out.flush();
                            continue;
                        }
                        
                        DBCommand command = (DBCommand) obj;
                        Object response = processCommand(command);
                        
                        out.writeObject(response);
                        out.flush();
                        
                        // 添加请求完成日志
                        System.out.println("[ClientHandler] 请求处理完成");
                    } catch (ClassNotFoundException e) {
                        System.err.println("[ClientHandler] 类找不到异常: " + e.getMessage());
                        e.printStackTrace();
                        
                        out.writeObject(new DBResponse(
                            DBResponse.Status.ERROR, 
                            "类找不到: " + e.getMessage()));
                        out.flush();
                    } catch (StreamCorruptedException e) {
                        System.err.println("[ClientHandler] 流损坏异常: " + e.getMessage());
                        e.printStackTrace();
                        
                        out.writeObject(new DBResponse(
                            DBResponse.Status.ERROR, 
                            "流损坏: " + e.getMessage()));
                        out.flush();
                    } catch (IOException e) {
                        if (e instanceof EOFException) {
                            System.out.println("[ClientHandler] 客户端断开连接: " + socket.getRemoteSocketAddress());
                            break; // 优雅退出循环
                        } else {
                            System.err.println("[ClientHandler] IO异常: " + e.getMessage());
                            e.printStackTrace();
                        }
                        break;
                    } catch (Exception e) {
                        System.err.println("[ClientHandler] 不可预期的异常: " + e.getMessage());
                        e.printStackTrace();
                        
                        out.writeObject(new DBResponse(
                            DBResponse.Status.ERROR, 
                            "内部错误: " + e.getClass().getSimpleName()));
                        out.flush();
                        break;
                    }
                }
            } catch (IOException e) {
                System.err.println("[ClientHandler] 连接异常中断: " + e.getMessage());
//                e.printStackTrace();
            } finally {
                try {
                    socket.close();
                    System.out.println("[ClientHandler] 客户端连接关闭: " + 
                        socket.getRemoteSocketAddress());
                } catch (IOException e) {
                    System.err.println("[ClientHandler] 套接字关闭失败: " + e.getMessage());
                }
            }
        }

        private Object processCommand(DBCommand command) {
            try {
                // 新增：复制命令直接交给集群管理器处理
                if (command.getType() == DBCommand.Type.REPLICATION) {
                    cluster.handleWrite(command);
                    return new DBResponse(DBResponse.Status.SUCCESS, "Replicated");
                }
                switch (command.getType()) {
                    case PUT: {
                        DBCommand.putCommand putCmd = (DBCommand.putCommand) command;

                        // 创建纯净数据（移除客户端可能传递的ID）
                        Map<String, Object> cleanData = new HashMap<>(putCmd.getData());
                        cleanData.remove("id"); // 防止客户端伪造ID

                        // 生成服务端ID并注入
                        String serverId = UUID.randomUUID().toString();
                        cleanData.put("id", serverId);

                        // 创建文档对象（使用服务端ID）
                        Document doc = new Document(putCmd.getCollection(), cleanData);

                        // 统一通过集群管理器处理写操作
                        cluster.handleWrite(new DBCommand.putCommand(
                                putCmd.getCollection(),
                                cleanData,
                                serverId
                                  // 含服务端ID的数据
                        ));

                        // 返回仅包含服务端ID的响应
                        return new DBResponse(DBResponse.Status.SUCCESS, serverId);
                    }

                    case GET:
                        DBCommand.GetCommand getCmd = (DBCommand.GetCommand) command;
                        Document doc = storage.get(getCmd.getCollection(),getCmd.getId());
                        // 返回包装后的响应
                        return new DBResponse(
                                doc != null ? DBResponse.Status.SUCCESS : DBResponse.Status.NOT_FOUND,
                                doc
                        );

                    case DELETE:
                        DBCommand.DeleteCommand delCmd = (DBCommand.DeleteCommand) command;
                        cluster.handleWrite(delCmd);
                        return new DBResponse(DBResponse.Status.SUCCESS,"DELETE SUCCESS");

                    case CREATE_COLLECTION:
                         DBCommand.CreateCollectionCommand createCmd = (DBCommand.CreateCollectionCommand) command;
                          cluster.handleWrite(createCmd);
                        // 实现创建集合
                        return new DBResponse(DBResponse.Status.SUCCESS,"CREATE SUCCESS");

                    // 修改UPDATE命令处理逻辑
                    case UPDATE: {
                        DBCommand.UpdateCommand updateCmd = (DBCommand.UpdateCommand) command;
                        try {
                            // 获取当前文档并注入版本号
                            Document currentDoc = storage.get(updateCmd.getCollection(), updateCmd.getId());
                            // +++ 新增：检查文档是否存在 +++
                            if (currentDoc == null) {
                                return new DBResponse(
                                        DBResponse.Status.NOT_FOUND,
                                        "文档不存在: " + updateCmd.getId()
                                );
                            }

                            Map<String, Object> updateData = new HashMap<>(updateCmd.getUpdateData());
                            updateData.put("_version", currentDoc.getTimestamp());

                            // 创建新的更新命令
                            DBCommand.UpdateCommand versionedCmd = new DBCommand.UpdateCommand(
                                    updateCmd.getCollection(),
                                    updateCmd.getId(),
                                    updateData
                            );

                            cluster.handleWrite(versionedCmd);

                            // 更新内存表中的数据
                            currentDoc.mergeData(updateData);
                            storage.getMemTable().put(currentDoc);
                            return new DBResponse(DBResponse.Status.SUCCESS, "更新成功");
                        } catch (IOException e) {
                            return new DBResponse(DBResponse.Status.ERROR, e.getMessage());
                        }
                    }

                    case LEADER_QUERY:
                        System.out.println("[DBServer] 处理LeaderQuery命令");
                        Node leader = cluster.getCurrentLeader();
                        System.out.printf("[DBServer] 返回Leader信息: %s (%s:%d)%n",
                                leader.getId(), leader.getHost(), leader.getPort());
                        return new DBCommand.LeaderResponse(leader);

                    case REPLICATION:
                        System.out.println("[处理] 复制命令");
                        cluster.handleWrite(command);
                        return new DBResponse(DBResponse.Status.SUCCESS, "复制成功");

                    case FLUSH:
                        System.out.println("[处理] 刷新命令");
                        cluster.manualFlush();
                        return new DBResponse(DBResponse.Status.SUCCESS, "刷新成功");
                    default:
                        return new DBResponse(DBResponse.Status.ERROR, "Unsupported command");
                }
            } catch (Exception e) {
                e.printStackTrace(); // 添加异常堆栈打印
                return new DBResponse(
                        DBResponse.Status.ERROR,
                        "Error: " + e.getClass().getSimpleName() + " - " + e.getMessage()
                );
            }
        }
    }
}